/* -*- jde -*- */
/* <Queue.java> */
package Practica5.structures;

/**
 * Clase que implementa una representación rápida de colas
 *
 * @author  Peralta Santa Anna Victor Miguel
 * @since	Julio 2011
 */
public class Queue<Type> {

    /**
     * Clase interna protegida para el manejo de los elementos de la cola.
     *
     * @param <T> El tipo de objeto para guardarlos en la cola
     */
    protected class Node<T> {

        /**
         *	Objeto elemento del nodo
         */
        public T data;
        /**
         * Nodo siguiente
         */
        public Node<T> next;

        /**
         * Constructor de un nodo
         *
         * @param data El elemento a guardar.
         */
        public Node(T data) {
            this.data = data;
            next = null;
        }
    } // Node Class

    /**
     * Clase interna de un Iterador para la clase Queue.
     *
     * @param <S> El elemento a guardar.
     */
    protected class Iterator<S> {

        /**
         * Nodo actual del iterador
         */
        public Node<S> current;

        /**
         * Iterador para la cola
         *
         * @param head el nodo en el cual se habrá de parar para iterar
         */
        public Iterator(Node<S> head) {
            current = head;
        }

        /**
         * Para saber si se tiene un siguiente elemento.
         *
         * @return verdadero si tiene un siguiente elemento, falso si no.
         */
        public boolean hasNext() {
            return current != null;
        }

        /**
         * Se mueve al siguiente elemento del iterador.
         */
        public void next() {
            current = current.next;
        }

        /**
         * Recupera el elemento dle nodo actual
         *
         * @return el elemento del nodo
         */
        public S retrive() {
            return (S) current.data;
        }
    } // Iterator
    /**
     * El inicio de la Cola
     */
    public Node<Type> front;
    /**
     * El útimo elemento de la cola
     */
    public Node<Type> tail;
    /**
     * tamaño de la cola
     */
    private long size;

    /**
     * Constructor sin parametros para una cola
     */
    public Queue() {
        front = tail = null;
        size = 0;
    }

    /**
     * enqueue // forma un elemento en la cola.
     *
     * @param obj El elemento a encolar
     */
    public void enqueue(Type obj) {
        Node<Type> node = new Node<Type>(obj);
        if (front != null) {
            tail.next = node;
            tail = node;
        } else {
            front = tail = node;
        }
        size++;
    }

    /**
     * dequeue // saca el elemento primero de la cola.
     *
     * @return el elemento que se saca de la cola
     */
    public Type dequeue() throws QueueException {
        if (front != null) {
            Type obj = front.data;
            front = front.next;
            size--;
            return obj;
        } else {
            throw new QueueException("Empty Queue -dequeue-");
        }
    }

    /**
     * front // devuelve el elemento primero de la cola.
     *
     * @return el elemento de enfrente de la cola
     */
    public Type front() throws QueueException {
        if (front != null) {
            return front.data;
        } else {
            throw new QueueException("Empty Queue -dequeue-");
        }
    }

    /**
     * isEmpty // regresa si la cola esta vacia.
     */
    public boolean isEmpty() {
        return front == null;
    }

    /**
     * size // regresa el tamaño de la cola.
     */
    public long size() {
        return size;
    }

    /**
     * Generamos un iterador para la cola.
     */
    public Iterator<Type> iterator() {
        return new Iterator(front);
    }
} // Stack class

